/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.isfd.constant.enums.IsfdBusinessDatabaseTypeEnum;
import com.comac.ins.isfd.domain.IsfdDatabaseModelTree;
import com.comac.ins.isfd.domain.bo.IsfdDatabaseModelTreeBo;
import com.comac.ins.isfd.domain.vo.IsfdDatabaseModelTreeShowVo;
import com.comac.ins.isfd.domain.vo.IsfdDatabaseModelTreeVo;
import com.comac.ins.isfd.domain.vo.IsfdDatabaseTypeManagementVo;
import com.comac.ins.isfd.mapper.IsfdDatabaseModelTreeMapper;
import com.comac.ins.isfd.mapper.IsfdDatabaseTypeManagementMapper;
import com.comac.ins.isfd.service.IIsfdDatabaseModelConfigService;
import com.comac.ins.isfd.service.IIsfdDatabaseModelTreeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 要素库模型层级管理Service业务层处理
 *
 * @author Lion Li
 * @date 2025-01-09
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class IsfdDatabaseModelTreeServiceImpl implements IIsfdDatabaseModelTreeService {

    @Autowired
    private IsfdDatabaseModelTreeMapper baseMapper;

    @Autowired
    private IIsfdDatabaseModelConfigService configService;

    @Autowired
    private IsfdDatabaseTypeManagementMapper isfdDatabaseTypeManagementMapper;

    @Override
    public IsfdDatabaseModelTreeShowVo getTree(Integer rootModelOnly) {
        // 获取根节点
        IsfdDatabaseModelTree root = baseMapper.selectOne(new LambdaQueryWrapper<IsfdDatabaseModelTree>().eq(IsfdDatabaseModelTree::getParentId, 0));
        if (root == null) {
            throw new BaseException("未找到根节点！");
        }
        // 一次性查询所有节点
        List<IsfdDatabaseModelTree> allNodes = baseMapper.selectList(null);

        // 构建父子节点映射
        Map<Long, List<IsfdDatabaseModelTree>> nodeMap = allNodes.stream()
            .filter(node -> node.getParentId() != null) // 过滤掉 parentId 为 null 的节点
            .collect(Collectors.groupingBy(IsfdDatabaseModelTree::getParentId));

        return createTree(root, nodeMap, rootModelOnly, null);
    }

    @Override
    public IsfdDatabaseModelTreeShowVo getTreeByBusinessId(Long databaseTypeId, Long sceneId, Long systemId, Integer rootModelOnly) {
        // 查询根节点
        IsfdDatabaseModelTree root = baseMapper.selectOne(new LambdaQueryWrapper<IsfdDatabaseModelTree>().eq(IsfdDatabaseModelTree::getParentId, 0));
        if (root == null) {
            throw new BaseException("未找到根节点！");
        }
        // 判断是几级库
        IsfdDatabaseTypeManagementVo isfdDatabaseTypeManagementVo = isfdDatabaseTypeManagementMapper.selectVoById(databaseTypeId);
        String uniqueKeyPrefix = root.getBusinessId() + "_" + databaseTypeId + "_" + sceneId;
        if (isfdDatabaseTypeManagementVo.getLevel() == 2) {
            Long parentId = isfdDatabaseTypeManagementVo.getParentId();
            IsfdDatabaseTypeManagementVo databaseLevel1 = isfdDatabaseTypeManagementMapper.selectVoById(parentId);
            uniqueKeyPrefix = root.getBusinessId() + "_" + databaseLevel1.getId() + "_" + databaseTypeId + "_" + sceneId;
        }

        String uniqueKey = uniqueKeyPrefix;
        IsfdBusinessDatabaseTypeEnum typeEnum = IsfdBusinessDatabaseTypeEnum.COMMON_MODEL;
        if (systemId != null) {
            uniqueKey = uniqueKeyPrefix + "_" + systemId;
            typeEnum = IsfdBusinessDatabaseTypeEnum.MODEL;
        }

        IsfdDatabaseModelTree parentTree = baseMapper.selectOne(new LambdaQueryWrapper<IsfdDatabaseModelTree>()
            .eq(IsfdDatabaseModelTree::getUniqueKey, uniqueKey));

        // 一次性查询所有节点
        List<IsfdDatabaseModelTree> allNodes = baseMapper.selectList(null);

        // 构建父子节点映射
        Map<Long, List<IsfdDatabaseModelTree>> nodeMap = allNodes.stream()
            .filter(node -> node.getParentId() != null) // 过滤掉 parentId 为 null 的节点
            .collect(Collectors.groupingBy(IsfdDatabaseModelTree::getParentId));
        IsfdDatabaseModelTreeShowVo treeShowVo = createTree(parentTree, nodeMap, rootModelOnly, typeEnum);

        // 只需要模型类型
        if (treeShowVo != null && !CollectionUtils.isEmpty(treeShowVo.getChildren())) {
            List<IsfdDatabaseModelTreeShowVo> modelList = treeShowVo.getChildren().stream().filter(t -> IsfdBusinessDatabaseTypeEnum.isModel(t.getType())).toList();
            treeShowVo.setChildren(modelList);
        }
        return treeShowVo;
    }

    /**
     * 构造树
     */
    private IsfdDatabaseModelTreeShowVo createTree(IsfdDatabaseModelTree node,
                                                   Map<Long, List<IsfdDatabaseModelTree>> nodeMap,
                                                   Integer rootModelOnly,
                                                   IsfdBusinessDatabaseTypeEnum typeEnum) {
        if (node == null) {
            return null;
        }
        // 将当前节点转换为视图对象
        IsfdDatabaseModelTreeShowVo nodeVo = MapstructUtils.convert(node, IsfdDatabaseModelTreeShowVo.class);

        // 获取该节点下的模型列表
        List<IsfdDatabaseModelTreeShowVo> modelList = configService.queryModelTreeListByNodeId(node.getId(), rootModelOnly, typeEnum);

        // 获取子节点列表
        List<IsfdDatabaseModelTree> children = nodeMap.getOrDefault(node.getId(), Collections.emptyList());

        List<IsfdDatabaseModelTreeShowVo> childNodes = new ArrayList<>();

        if (CollectionUtil.isNotEmpty(children)) {
            // 遍历子节点并递归调用
            childNodes.addAll(children.stream()
                .map(child -> createTree(child, nodeMap, rootModelOnly, typeEnum)) // 递归调用，传入子节点
                .toList());
        }
        if (CollectionUtil.isNotEmpty(modelList)) {
            childNodes.addAll(modelList);
        }
        nodeVo.setChildren(childNodes);
        return nodeVo;
    }

    @Override
    @Transactional
    public Boolean save(IsfdDatabaseModelTreeBo bo) {
        IsfdDatabaseModelTree po = MapstructUtils.convert(bo, IsfdDatabaseModelTree.class);
        IsfdBusinessDatabaseTypeEnum typeEnum = IsfdBusinessDatabaseTypeEnum.forValue(bo.getType());
        if (typeEnum == null) {
            throw new BaseException("不是支持的类型：" + bo.getType() + " 支持的类型：" + Arrays.toString(IsfdBusinessDatabaseTypeEnum.values()));
        }
        Long parentId = po.getParentId();
        if (parentId == null) {
            throw new BaseException("父节点不能为空！");
        }
        IsfdDatabaseModelTree parentPo = baseMapper.selectById(parentId);
        if (parentPo == null) {
            throw new BaseException("父节点不能为空！");
        }
        Long businessId = bo.getBusinessId();
        String parentUniqueKey = parentPo.getUniqueKey();
        Long topId = parentPo.getTopId();
        String uniqueKey = parentUniqueKey + "_" + businessId;
        // 如果 新增的是 库类型二级库
        if (typeEnum.getValue().equals(IsfdBusinessDatabaseTypeEnum.DATABASE_2.getValue())) {
            // 如果 父节点是 root节点，需要判断是否 库类型一级库存在
            if (parentPo.getType().equals(IsfdBusinessDatabaseTypeEnum.ROOT.getValue())) {
                IsfdDatabaseTypeManagementVo databaseVo = isfdDatabaseTypeManagementMapper.selectVoById(businessId);
                if (databaseVo != null) {
                    Long databaseVoParentId = databaseVo.getParentId();
                    IsfdDatabaseTypeManagementVo databaseParentVo = isfdDatabaseTypeManagementMapper.selectVoById(databaseVoParentId);
                    String databaseLevel1UniqueKey = parentUniqueKey + "_" + databaseParentVo.getId();
                    IsfdDatabaseModelTreeVo parentTreeVo = this.queryByUniqueKey(databaseLevel1UniqueKey);
                    if (parentTreeVo == null) {
                        IsfdDatabaseModelTree dataBaseLevel1 = new IsfdDatabaseModelTree();
                        dataBaseLevel1.setTopId(topId);
                        dataBaseLevel1.setParentId(parentId);
                        dataBaseLevel1.setName(databaseParentVo.getDatabaseName());
                        dataBaseLevel1.setBusinessId(databaseParentVo.getId());
                        dataBaseLevel1.setUniqueKey(databaseLevel1UniqueKey);
                        dataBaseLevel1.setType(IsfdBusinessDatabaseTypeEnum.DATABASE_1.getValue());
                        baseMapper.insert(dataBaseLevel1);

                        uniqueKey = databaseLevel1UniqueKey + "_" + businessId;
                        parentId = dataBaseLevel1.getId();
                    } else {
                        uniqueKey = databaseLevel1UniqueKey + "_" + businessId;
                        parentId = parentTreeVo.getId();
                    }
                }
            }
        }
        // 校验唯一值
        if (this.queryByUniqueKey(uniqueKey) != null) {
            throw new BaseException("该节点下已经存在相应子节点：" + bo.getName() + "，不能添加重复节点！");
        }
        po.setParentId(parentId);
        po.setTopId(topId);
        po.setUniqueKey(uniqueKey);
        baseMapper.insert(po);
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        //删除节点
        IsfdDatabaseModelTree node = baseMapper.selectById(id);
        if (node == null) {
            throw new BaseException("无法找到该节点！id: " + id);
        }
        // 一次性查询所有节点
        List<IsfdDatabaseModelTree> allNodes = baseMapper.selectList(
            new LambdaQueryWrapper<IsfdDatabaseModelTree>()
                .isNotNull(IsfdDatabaseModelTree::getParentId)
        );
        // 构建父子节点映射
        Map<Long, List<IsfdDatabaseModelTree>> nodeMap = allNodes.stream()
            .collect(Collectors.groupingBy(IsfdDatabaseModelTree::getParentId));

        List<Long> subNodeIds = getSubNodeIds(node, nodeMap);

        try {
            for (Long subNodeId : subNodeIds) {
                configService.deleteConfigByNodeId(subNodeId); // 确保抛出异常时传播到 deleteByIds
            }
            baseMapper.deleteBatchIds(subNodeIds); // 删除所有子节点
        } catch (Exception e) {
            throw new BaseException("删除操作失败", e.getMessage()); // 捕获并重新抛出以触发事务回滚
        }
        return true;
    }

    @Override
    public IsfdDatabaseModelTreeVo queryByUniqueKey(String uniqueKey) {
        return baseMapper.selectVoOne(new LambdaQueryWrapper<IsfdDatabaseModelTree>().eq(IsfdDatabaseModelTree::getUniqueKey, uniqueKey));
    }

    @Override
    public void checkIfNodeExist(IsfdBusinessDatabaseTypeEnum isfdBusinessDatabaseTypeEnum, Long businessId, String name) {
        String type = isfdBusinessDatabaseTypeEnum.getValue();
        String desc = isfdBusinessDatabaseTypeEnum.getDesc();
        List<IsfdDatabaseModelTreeVo> treeList = baseMapper.selectVoList(new LambdaQueryWrapper<IsfdDatabaseModelTree>()
            .eq(IsfdDatabaseModelTree::getType, type)
            .eq(IsfdDatabaseModelTree::getBusinessId, businessId));
        if (!CollectionUtils.isEmpty(treeList)) {
            throw new BaseException("当前" + desc + ": " + name + "，已经在模型关联关系中存在，不可删除或者修改节点位置，请确认后重试！");
        }
    }

    private List<Long> getSubNodeIds(IsfdDatabaseModelTree node, Map<Long, List<IsfdDatabaseModelTree>> nodeMap) {
        // 获取当前节点的子节点列表
        List<IsfdDatabaseModelTree> children = nodeMap.get(node.getId());
        if (CollectionUtil.isEmpty(children)) {
            // 如果没有子节点，则返回一个只包含当前节点的列表
            return List.of(node.getId());
        }
        // 初始化一个列表来保存所有的子节点（包括递归获取的子孙节点）
        List<Long> allNodeId = new ArrayList<>();
        allNodeId.add(node.getId()); // 添加当前节点
        // 遍历子节点并递归获取子孙节点
        for (IsfdDatabaseModelTree child : children) {
            allNodeId.addAll(getSubNodeIds(child, nodeMap));
        }
        return allNodeId;
    }
}
